import java.util.ArrayList;
import java.util.List;

public class Test04 {
    public static void main(String[] args) {
        //创建ArrayList对象，构造一个空的顺序表
        ArrayList<String> arr = new ArrayList<>();//空盒子
        ArrayList<String> arr2 = null;//盒子都没有

        //第二种创建方式
        List<String> list = new ArrayList<>();//后续针对 List 进行各种方法调用就会触发多态

        //使用 arrayList 复制一份 ， 生成 arrayList3
        ArrayList<String> arr3 = new ArrayList<>(arr);
        ArrayList<String> arr4 = new ArrayList<>(10);//超过10个可动态扩容

        //添加元素
        List<String> arr5 = new ArrayList<>(arr);
        //add 这样的方法 ， 内部就会涉及到自动扩容
        System.out.println(arr5.size());
        arr5.add("aaa");
        arr5.add("bbb");
        arr5.add("ccc");
        System.out.println(arr5);//集合类一般都是可以打印店

        //获取元素的个数 数组提供了 .length 属性获取元素个数 ， 集合类提供了 size() 方法获取元素个数
        System.out.println(arr5.size());

        //获取List中的元素 .get()/设置.set(index, )
        List<String> arr6 = new ArrayList<>(arr);
        //add 这样的方法 ， 内部就会涉及到自动扩容
        arr6.add("aaa");
        arr6.add("bbb");
        arr6.add("ccc");
        arr6.add("ddd");
        System.out.println(arr6.get(0));
        System.out.println(arr6.get(1));
        System.out.println(arr6.get(2));
        System.out.println(arr6.get(3));

        arr6.set(1,"eee");
        System.out.println(arr6.get(1));
        System.out.println("==============");
        //为什么 List 不能像数组用 [] 来操作

        //遍历可能会进行各种操作 ， 不一定是打印
        for (int i = 0; i < arr6.size(); i++) {
            System.out.println(arr6.get(i));
        }
        System.out.println();
        //for each
        //什么样的类可以使用for each 遍历 ？ 要求这个类必须实现 Iterable 接口中的 iterator 方法 ， 得到一个迭代器对象 ， 进一步的循环


        for(String s : arr6) {
            System.out.println(s);
        }

        //hasNext()判断有没有下一个元素
        //next() 取出当前元素并且准备去下一个元素

        System.out.println("============");
        //在任意位置添加元素

        List<String> list2 = new ArrayList<>();
        list2.add("aaa");
        list2.add("bbb");
//        list2.add("ccc");
        //注意这里的下标的含义：往指定下标之前插入元素/添加完毕后新元素的下标就是这个数值 ，
        //虽然list当中不存在下标为2的元素 ， 但是此处的添加就相当于“尾插”
        list2.add(2,"fff");
        System.out.println(list2);

        System.out.println("=========");
        //删除元素
        //一 按下标来删除
        List<String> list3 = new ArrayList<>();
        list3.add("aaa");
        list3.add("bbb");
        list3.add("ccc");
        list3.add("ccc");
        list3.add("ddd");
        System.out.println(list3);
//        list3.remove(1);
//        System.out.println(list3);
        //按照下表来删除元素
        list3.remove("ccc");
        System.out.println(list3);

        //以list3 为例 ，通过 contains判定元素是否存在
        list3.contains("aaa");//true

        //以list3 为例 ，通过 indexOf() 获取元素的下标 ,从前往后找找到第一个就返回了
        System.out.println(list3.indexOf("ccc"));//2
        System.out.println(list.indexOf("hhh"));//-1
        System.out.println(list3);
        System.out.println("===========");


        //通过 subList 得到子列表
        List<String> sublist = list3.subList(1,3);//[1,3)
        System.out.println(sublist);

        System.out.println("=========");
        sublist.set(0,"111");
        //子列表操作 ， 不是创建“副本列表” ， 而是直接取代原始列表的一部分进行构造 ， 修改子列表会影响原始列表
        //如果不想修改到原始列表可以将List<String> sublist = list3.subList(1,3);  改为List<String> sublist =new ArrayList<>(list3.subList(1,3)); 相当于复制了一份
        //String 作为不可变对象就没有这样的烦恼
        System.out.println(list3);//[aaa, 111, ccc, ddd] , list3 也被修改了

        System.out.println("============");
        List<String> list4 = new ArrayList<>();
        list4.add("aaa");
        list4.add("bbb");
        list4.add("ccc");
        list4.add("ccc");
        list4.add("ddd");
        System.out.println(list4);
        list4.clear();//得到的是空盒子
        System.out.println(list4);


        //java中存在垃圾回收机制（GC），无论是通过 remove 删除的元素还是通过 clear 删除的元素，还是通过 list = null list中包含的元素的内存空间，都能被释放掉
        //都是JVM自动完成的

        /*
        ArrayList 内部持有一个数组 ， 设置的初始容量 ， 就相当于数组的大小
        
         */

    }
}
